import api from './api'

const urlReg = new RegExp('(https?|ftp|file)://[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]', 'g');

export const API = api;
import moment from 'moment'
import md5 from 'md5'
import {Toast} from 'antd-mobile'

import DeviceInfo from 'react-native-device-info'

import {Platform, Alert, Linking, AsyncStorage} from 'react-native'

import {API_SECRET, GD_MAP_KEY, ERROR_MSG_DURATION} from './constant'


const isDebug = !api.PRODUCTION;
let API_BASE_URI = API.RELEASE;
if (isDebug) {
    API_BASE_URI = API.DEBUG;
}

const checkResponse = (response, apiUrl) => {
    return new Promise((resolve, reject) => {
        if (response.code === 200) {
            resolve(response)
        }
        else {
            Toast.fail(response.message, ERROR_MSG_DURATION);
        }
    })
};

const makeHeaders = (params, timestamp) => {
    return {
        //'Content-type' : 'application/json' ,//js 解决跨域问题(web)
        'timestamp': timestamp,
        'device': DeviceInfo.getBrand() + ' ' + DeviceInfo.getModel(),
        'device-os-version': DeviceInfo.getSystemVersion(),
        'app-version': '1.0',
        'signature': signature(params, timestamp)
    }
};

//签名
const signature = (params, timestamp) => {
    let metaData = [];
    metaData.push('timestamp=' + timestamp)
    for (let key in params) {
        if (!params.hasOwnProperty(key)) {
            continue
        }
        metaData.push(key + '=' + params[key])
    }
    metaData.sort(function (a, b) {
        return a < b
            ? -1
            : 1
    });
    metaData.push('secret=' + API_SECRET)
    return md5(metaData.join('&'))
};

export const makeQueryString = (params) => {
    if (!params) {
        return ''
    }
    let query = []
    for (let key in params) {
        if (!params.hasOwnProperty(key)) {
            continue
        }
        query.push(`${key}=${params[key]}`)
    }

    return '?' + query.join('&')
};

const makeFormData = (params = {}) => {
    const formData = new FormData()
    for (let key in params) {
        if (!params.hasOwnProperty(key)) {
            continue
        }
        formData.append(key, params[key])
    }
    return formData
};

export async function get(url, params = {}, inapp = true) {

    let apiUrl = '';
    if (inapp) {
        apiUrl = API_BASE_URI + url + makeQueryString(params);
    } else {
        apiUrl = url + makeQueryString(params);
    }
    return fetch(apiUrl, {
        method: 'GET',
    }).then((response) => {
        if (response.status === 200) {
            return response.json()
        } else {
            console.log(apiUrl, response);
            throw  new Error('网络错误')
        }
    }).then((response) => {
        if (response.code === 200) {
            return response;
        }
        else {
            console.log(apiUrl,response, params);
            Toast.fail(JSON.stringify(response.message), ERROR_MSG_DURATION);
            return null;
        }
    }).catch((e) => {
        console.log(e, apiUrl);
        Toast.fail(e.message, ERROR_MSG_DURATION);
    });
}


export async function put(url, params = {}) {
    const apiUrl = API_BASE_URI + url
    const timestamp = moment().format('X')

    const response = await fetch(apiUrl, {
        method: 'PUT',
        headers: makeHeaders(params, timestamp),
        body: JSON.stringify(params)
    })

    const responseData = await response.json()
    checkResponse(responseData, apiUrl)
    return responseData
};


export function post(url, params = {}, inapp = true) {
    let apiUrl = '';
    if (inapp) {
        apiUrl = API_BASE_URI + url;
    } else {
        apiUrl = url;
    }
    return fetch(apiUrl, {
        method: 'POST',
        body: makeFormData(params)
    }).then((response) => {
        if (response.status === 200) {
            return response.json()
        } else {
            console.log(apiUrl, response);
            throw  new Error('网络错误')
        }

    }).then((response) => {
        if (response.code === 200) {
            return response;
        }
        else {
            console.log(apiUrl, response, params);
            Toast.fail(JSON.stringify(response.message), ERROR_MSG_DURATION);
            return null;
        }
    }).catch((e) => {
        console.log(e, apiUrl);
        Toast.fail(e.message, ERROR_MSG_DURATION);
    });
};


export async function remove(url, params = {}) {
    const apiUrl = API_BASE_URI + url
    const timestamp = moment().format('X')

    const response = await fetch(apiUrl, {
        method: 'DELETE',
        headers: makeHeaders(params, timestamp),
        body: JSON.stringify(params)
    })

    const responseData = await response.json()
    checkResponse(responseData, apiUrl)
    return responseData
};

export async function upload(params, formData = {}) {
    const apiUrl = API_BASE_URI + 'system/upload'
    const timestamp = moment().format('X')
    const headers = makeHeaders(params, timestamp)
    //console.log('upload',params);
    const opt = {
        method: 'POST',
        headers,
        body: formData
    }
    const response = await fetch(apiUrl, opt)
    const responseData = await response.json()
    checkResponse(responseData, apiUrl)
    return responseData
};

export const getPromise = (url, params = {}, inapp) => {

    let apiUrl = '';
    if (inapp) {
        apiUrl = API_BASE_URI + url + makeQueryString(params);
    } else {
        apiUrl = url + makeQueryString(params);
    }
    return fetch(apiUrl, {
        method: 'GET',
    }).then((response) => {
        if (inapp) {
            if (response.status === 200) {
                return response.json()
            } else {
                console.log(apiUrl, response);
                throw  new Error('网络错误')
            }
        } else {
            return response.json();
        }

    }).then((response) => {
        if (inapp) {
            if (response.code === 200) {
                return response;
            }
            else {
                console.log(response, params);
                Toast.fail(JSON.stringify(response.message), ERROR_MSG_DURATION);
                return null;
            }
        } else {
            return response
        }


    }).catch((e) => {
        console.log(e, apiUrl);
        Toast.fail(e.message, ERROR_MSG_DURATION);
    });
};

export const postPromise = (url, params = {}, inApp = true) => {
    const apiUrl = (inApp
        ? API_BASE_URI
        : '') + url
    const options = {
        method: 'POST',
        body: makeFormData(params)
    }
    return fetch(apiUrl, options).then((response) => {
        return response.json()
    }).then((response) => {
        checkResponse(response, apiUrl)
        return response
    })
};

//ios端打开系统定位设置
const openLocationSetting = (cancelCallBack) => {
    Alert.alert('定位信息获取失败', '邻家优儿需要定位权限,现在打开?' + '或者在设置->隐私->定位服务->邻家优儿中自行打开', [
        {
            text: '确定',
            onPress: () => {
                Linking.canOpenURL('prefs:root=LOCATION_SERVICES').then((supported) => {
                    if (supported) {
                        Linking.openURL('prefs:root=LOCATION_SERVICES')
                    }
                })
            }
        }, {
            text: '取消',
            onPress: cancelCallBack
        }
    ])
};

//获取ip定位信息
//返回Promise
export const getIpGeo = (params = {}) => {
    const geoApi = api.geo + makeQueryString({
        key: GD_MAP_KEY,
        ...params
    })
    return fetch(geoApi, {method: 'GET'}).then((response) => {
        return response.json()
    }).then((response) => {
        let rectangle = response.rectangle.split(';')
        let positions = []
        positions.push(rectangle[0].split(','))
        positions.push(rectangle[1].split(','))
        const lng = (parseFloat(positions[0][0]) + parseFloat(positions[1][0])) / 2
        const lat = (parseFloat(positions[0][1]) + parseFloat(positions[1][1])) / 2
        return {
            ...response,
            position: {
                lat,
                lng
            }
        }
    })
};

//获取gps定位信息
//在ios端如果由于定位权限被拒绝会提示打开定位权限
//返回Promise
export const getGpsGeo = (options = {}) => {
    return new Promise((resolve, reject) => {
        navigator.geolocation.getCurrentPosition(({
                                                      coords: {
                                                          latitude,
                                                          longitude
                                                      }
                                                  }) => {
            resolve({lat: latitude, lng: longitude})
        }, reject, {
            enableHighAccuracy: true,
            timeout: 20000,
            maximumAge: 1000,
            ...options
        })
    })
};

//获取定位信息
//先获取gps定位信息
//失败则获取ip定位信息
//返回Promise
export const getGeolocation = () => {
    return new Promise((resolve, reject) => {
        const _getGeo = () => {
            getGpsGeo().then((position) => {
                console.log('GPS定位', position)
                AsyncStorage.setItem('geoLocation', JSON.stringify({
                    ...position,
                    timestamp: moment().format('X')
                }))
                resolve(position)
            }).catch((error) => {
                console.log(error)
                if (error.code === 1 || error.code === 2 && Platform.OS === 'ios') {
                    openLocationSetting(() => {
                        getIpGeo().then(({position}) => {
                            AsyncStorage.setItem('geoLocation', JSON.stringify({
                                ...position,
                                timestamp: moment().format('X')
                            }))
                            resolve(position)
                        }).catch(reject)
                    })
                } else {
                    getIpGeo().then(({position}) => {
                        console.log('IP定位', position)
                        AsyncStorage.setItem('geoLocation', JSON.stringify({
                            ...position,
                            timestamp: moment().format('X')
                        }))
                        resolve(position)
                    }).catch(reject)
                }
            })
        }

        AsyncStorage.getItem('geoLocation').then((res) => {
            //有缓存
            if (res) {
                let geo = JSON.parse(res)

                console.log(moment().format('X') - parseInt(geo.timestamp))
                //过期
                if (moment().format('X') - parseInt(geo.timestamp) > GEO_CATCH_TIME) {
                    //未过期
                    _getGeo()
                } else {
                    //_getGeo();
                    resolve({lat: geo.lat, lng: geo.lng})
                }
                //无缓存
            } else {
                _getGeo()
            }
        }).catch((err) => {

            _getGeo()
        })
    })
};

//use only for post or get
export const fetchDataWithLocation = (url = '', method = '', params = {}) => {
    return new Promise((resolve, reject) => {
        if (!url || url.length <= 0) {
            reject(new Error('请求url误' + url))
        }
        getGeolocation().then(({lat, lng}) => {
            console.log(lat, lng)
            switch (method.toUpperCase()) {
                case 'GET':
                    return getPromise(url, {
                        ...params,
                        lng,
                        lat
                    }).then(resolve).catch(reject)
                case 'POST':
                    return postPromise(url, {
                        ...params,
                        lng,
                        lat
                    }).then(resolve).catch(reject)
                default: {
                    reject(new Error('请求方法有误'))
                }
            }
        }).catch(reject)
    })
};

export const checkImageUrl = (src) => {
    if (typeof src === 'string') {
        if (urlReg.test(src)) {
            return url;
        } else {
            return API_BASE_URI + '/' + src;
        }
    }
    else if (urlReg.test(src.uri)) {
        return src;
    } else {
        return {
            ...src, uri: API_BASE_URI + '/' + src.uri
        }
    }
};